package edu.umd.ion.wavemeter.client;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.DOM;

import edu.umd.ion.wavemeter.service.ChannelEvent;
import edu.umd.ion.wavemeter.service.ErrorMessages;
import edu.umd.ion.wavemeter.service.WavemeterChannelData;
import edu.umd.ion.wavemeter.service.WavemeterServiceAsync;

/**
 * Basic Sub-Widget implementing a cell in the table of wavelength results.
 * This class only implements the wavelength display. The detail controls and
 * displays are implemented in derived classes.
 */
public class WavemeterSimpleChannelWidget extends WavemeterChannelWidgetBase  {
	/**
	 *  The wavelength display itself.
	 */
	protected Label WavelengthLabel;
	
	/**
	 *  Display of server errors
	 */
	protected Label ErrorLabel;
		
	protected String OldColor = "";
	protected String OldBackgroundColor = "";
	
	private int LastMouseDownX, LastMouseDownY;

	private AsyncCallback<Void> CommandCallback = new AsyncCallback<Void>() {
		public void onFailure(Throwable caught) {
			try {
				//ErrorLabel.setHTML("Command: " + caught.getMessage());
				throw caught;
			} catch (IncompatibleRemoteServiceException e) {
				// this client is not compatible with the server; cleanup and refresh the 
				// browser
			} catch (Throwable e) {
				// last resort -- a very unexpected exception
			}	
		}

		public void onSuccess(Void result) {
			//ErrorLabel.setHTML("");
		}
	};
	
	/**
	 * Update the data displayed by this widget
	 * @param data
	 */
	public void set(WavemeterChannelData data)
	{
		super.set(data);
		if (Active) {
			if (data.InterlockEnabled) {
				if (data.InterlockInRange) {
					setWavelengthLabelColor(inRangeColor);
				} else {
					setWavelengthLabelColor(outOfRangeColor);
				}
			} else {
				setWavelengthLabelColor(activeColor);
			} 
		} else {
			setWavelengthLabelColor(inactiveColor);
		} 
		if (data.LockEnabled) {
			boolean OutOfLock = false;
			double MySetPoint = data.PIDSetWavelength;
			try {
				if (MySetPoint==0 && data.PIDCourse!=null) {
					String PeriodCourse = data.PIDCourse.trim();
					MySetPoint = Double.parseDouble(PeriodCourse);
				}
				OutOfLock = Math.abs(MySetPoint-data.Wavelength)>OutOfLockDeviation;
			} catch (NumberFormatException Ex) {
			}
			if (OutOfLock) {
				setWavelengthBackgroundColor(outOfLockBackgroundColor);
			} else {
				setWavelengthBackgroundColor(lockedBackgroundColor);
			}
		} else {
			setWavelengthBackgroundColor(backgroundColor);			
		}
		if (data.Wavelength>0) {
			WavelengthLabel.setText(UnitBox.convert(data.Wavelength));
			WavelengthLabel.setVisible(true);
			ErrorLabel.setVisible(false);
		}
		else if (data.Wavelength>-16)
		{
			ErrorLabel.setText( ErrorMessages.WavelengthErrors[-((int) data.Wavelength)]);
			WavelengthLabel.setVisible(false);
			ErrorLabel.setVisible(true);
		}
	}
	
	public void setWavelengthLabelHeight(String height)
	{
		if (height!=null)
		{
			com.google.gwt.user.client.Element Element = WavelengthLabel.getElement();
			DOM.setStyleAttribute(Element, "fontSize", height); 
			com.google.gwt.user.client.Element ErrorElement = ErrorLabel.getElement();
			DOM.setStyleAttribute(ErrorElement, "fontSize", height); 
		}
	}
	
	public void setWavelengthLabelColor(String color)
	{
		if (!color.equals(OldColor)) {
			com.google.gwt.user.client.Element Element = WavelengthLabel.getElement();
			DOM.setStyleAttribute(Element,"color", color);
			com.google.gwt.user.client.Element ErrorElement = ErrorLabel.getElement();
			DOM.setStyleAttribute(ErrorElement,"color", color);
			OldColor = color;
		}
	}

	public void setWavelengthBackgroundColor(String color)
	{
		if (!color.equals(OldBackgroundColor)) {
			com.google.gwt.user.client.Element element = WavelengthLabel.getElement();
			DOM.setStyleAttribute(element,"backgroundColor", color);
			OldBackgroundColor = color;
		}
	}
	
	private MouseDownHandler myMouseDownHandler = new MouseDownHandler() {
		@Override
		public void onMouseDown(MouseDownEvent event) {
			LastMouseDownX = event.getClientX();
			LastMouseDownY = event.getClientY();
		}
	};
	
	private MouseUpHandler myMouseUpHandler = new MouseUpHandler() {
		@Override
		public void onMouseUp(MouseUpEvent event) {
			ChannelEvent MyChannelEvent = new ChannelEvent(ChannelNumber, ChannelEvent.MOUSE_CLICK );
			MyChannelEvent.setAltDown(event.isAltKeyDown());
			MyChannelEvent.setControlDown(event.isControlKeyDown());
			MyChannelEvent.setShiftDown(event.isShiftKeyDown());
			MyChannelEvent.setMetaDown(event.isMetaKeyDown());
			MyChannelEvent.setXMovement(event.getClientX()-LastMouseDownX);
			MyChannelEvent.setYMovement(event.getClientY()-LastMouseDownY);
			WavemeterService.raiseChannelEvent(MyChannelEvent, CommandCallback);				
		}};
	
	public WavemeterSimpleChannelWidget(WavemeterServiceAsync service, int Number, boolean showunit, Panel errorPanel )
	{
		super(service,Number,showunit,errorPanel);
		
		// Vertical Panel
		WavelengthLabel = new Label();
		WavelengthLabel.setStylePrimaryName("layout-WavelengthLabel");
		WavelengthLabel.addMouseUpHandler( myMouseUpHandler );
		WavelengthLabel.addMouseDownHandler( myMouseDownHandler );
		ErrorLabel = new Label();
		ErrorLabel.setStyleName("layout-WavelengthErrorLabel");
		ErrorLabel.addMouseUpHandler(myMouseUpHandler);
		ErrorLabel.addMouseDownHandler(myMouseDownHandler);
		ErrorLabel.setVisible(false);
	}
	
	public void initialize(com.google.gwt.xml.client.Element domelement) {
		VerticalPanel vert = new VerticalPanel();
		vert.setHorizontalAlignment(VerticalPanel.ALIGN_LEFT);
		vert.add(WavelengthLabel);
		vert.add(ErrorLabel);
		vert.setStyleName("layout-ChannelVertWidget");

		// wrap everything in disclosure panel
		initWidget(vert);		
	}
	
 	public int getChannelNumber() {
		return ChannelNumber;
	}
 	
}
